I was working on a graphics routine last week, and learned how to use the MouseX and MouseY values to execute a branch label. Wow! This is terribly cool! I wished I had someone to show the program to! There must have been a Bottle Imp somewhere near my workstation who heard my request. Suddenly an animated image appeared atop the code displayed on my monitor.
He was a rotund fellow, spherical actually, wearing an artist's smock, a black beret, and holding an artists palette with several brushes in his left hand. His hair was long and straggly and he was huffing and puffing, obviously out of breath. I'm accustomed to weird happenings when I am programming in LB, so I was not taken aback.

"Hi there," I said, rather smugly. "Who are you?"
"I'm Pablo Worble, Bill, no relation to Picasso, but I am the Artist in Charge of Drawing All Your Windows. I know you're very proud of that new program you've written, but it's messier than a kitten playing with a ball of yarn and you've got me and my assistants running all over the monitor by calling us from a dozen places in your code! Can't you tidy it up a little? Look at all the places you are redrawing in that temporary window, and you've written three routines to pause before returning to the [setUp] code. Wouldn't it be easier to execute the pause with a single sub-routine? And look at all the branch routines where you've typed 14 lines of code, just to use one of three colors. You can make that much neater with a small SELECT CASE block. The only thing you want to do is change the color and message for the same window. Right? Make it easy on yourself, and me too! I've been around the CPU many years, but I have to keep running back to your code to see what you want me to do."
This didn't surprise me much. I will be forever learning how to simplify the code I write and, Pablo being a Worble, I figured I could learn much from him. "Well, I began by writing a few lines of code to go to a branch-label if the mouse clicked on a target. I thought I did a really excellent job, but you Worbles are so good with code, I'll be happy to listen to you," I told him. "Where should I start?"
"How about your pause routine? You're using the same pause in three places and each pause requires four lines of code. Put those four lines into a sub-routine like this, then you can CALL shortPause from anywhere in your code. While you're testing your code, you only have to change the TIMER value once, and it will be used with each CALL you issue.
SUB shortPause
PRINT #cw, "disable"
TIMER 2000, [cont] 'Set pause here, more is longer.
WAIT
[cont]
TIMER 0
PRINT #cw, "enable"
END SUB
"Why do we have "disable" and "enable" in the sub-routine, Pablo?"
"Because some users cannot resist trying to crash your program, Bill. If you click on the graphics window while the program is in pause-mode, you'll crash with an 'invalid branch label error'. Sub-routines cannot see labels in the main program, so we prevent the user from doing that by disabling the main window. When inside the shortPause Sub, a mouse click won't be recognized."
"Hey, that's better than sliced bread, Pablo! Thanks for the suggestion!"
"Think nothing of it. It runs in my family. Now, you have three branch routines here, and their only purpose is to change the color of one object on your window and the message presented to the user. What say we rewrite that to use string variables for the color and message?"
"Err, that sounds like it will work, but how do I do that?"
"Let's go to the MouseX and MouseY comparisons you've made. You could have used BMP buttons, or sprite images, but your code does not require adding BMP images to the program, so it's pretty good in that respect. Instead of saying If this equals that, and that equals this, then do this, why don't we assign a value to the choice and then use SELECT CASE to assign the color to col$, the place where you want your color printed to loc$, and the message to msg$?
IF (MouseX >12 AND MouseX < 28) AND (MouseY >12 and MouseY <28) THEN sel=1
IF (MouseX >12 AND MouseX < 28) AND (MouseY >52 and MouseY <68) THEN sel=2
IF (MouseX >12 AND MouseX < 28) AND (MouseY >92 and MouseY <108) THEN sel=3
SELECT CASE sel 'Set new colors and message
CASE 1 'Green button is pressed
col$="GREEN"
msg$="GREEN!"
loc$="20 20"
CASE 2 'Yellow button is pressed
col$="YELLOW"
msg$="YELLOW!"
loc$="20 60"
CASE 3
col$="RED" 'Red button is pressed
msg$="RED!"
loc$="20 100"
CASE ELSE
GOTO [setUp]
END SELECT
"You could tighten up those MouseX MouseY ranges to make smaller targets if you wish. I added CASE ELSE because some people cannot resist fiddling with things. If the user clicks the window outside the target areas, the program does nothing except go back to [setUp] to wait for proper input. Now that my assistants know what color you want to use, where you want it printed, and the message to display, we can order a few pints of paint based upon your SELECT CASE statement, and then proceed to [tempSetup] to do what you ask."
Pablo deleted those three branch routines I had spent all day writing, and easily inserted several lines to do the same task, but using about one-third as many lines. His code ended up looking like this…
[tempSetup] 'Draw Temp Window PRINT #cw, "place 10 140" 'Places the pen PRINT #cw, "down" PRINT #cw, "backcolor "; col$ 'Set a new color based on button pressed PRINT #cw, "place "; loc$ 'Position the pen PRINT #cw, "circlefilled 10" 'Draw a filled circle PRINT #cw, "place 10 140" 'Places the pen PRINT #cw, "backcolor buttonface" 'Background color of the text PRINT #cw, "\You pressed "; msg$ 'Message to user CALL shortPause 'Do shortPause then come back here sel=0 : MouseX=0 : MouseY=0 'Re-set values to zero before new [setUp] GOTO [setUp] 'Go back to the Default Window
"Pablo, you sure know a lot of neat tricks, I have to admit. How about a short cut to use if I need a color that's not one of the 16 standard colors in basic? I can't make heads nor tails out of RGB values, so I just plug in some numbers and see what happens. It takes a lot of trial and error before I get the numbers even close to what I want."
"So that's what you call it, trial and error. Why didn't you do it the easy way?"
"Easy way? How?"
"Use the Liberty BASIC colordialog command. We know exactly where to find it and we've had lots of practice using it."
First Pablo showed me the code.

Colordialog oldColor$, newColor$
Print newColor$
Then Pablo put an image up on the monitor.
"You can use your favorite imaging program, but this is the way we Worbles do it in Liberty BASIC. First, run the code to view the Colordialog. Then click on Define Custom Colors. Suppose we want a shade of green; click your mouse on the approximate color you want, then move the slider on the right up or down to choose the intensity for the color which appears in the Color/Solid window. Your RGB values will be shown in the three boxes in the lower right corner. You can also retrieve the RGB values in the variable newColor$"
"Shazaam, Pablo! I didn't know it was that simple! I kept changing the number a little at a time and running the program. I must have spent an hour getting each color correct, and I had three colors to work with."
"We know, Bill, we were the ones who kept repainting your window!" Pablo gave me a scolding look.
"Is there anything more I should do to clean up this code, Pablo?"
"I think it looks much better now, Bill. Your original code was 4.48KB and the new code is only 3.14KB, including all those useful remarks you inserted. Why don't you run it now and see if you're satisfied?"
The new code did indeed look better. When Pablo was all finished, this is what I had...
'Using SELECT CASE Branch To with SUB for Delay and Re-Draw a Window
'Written by Welopez with Help from Pablo, 051305
NOMAINWIN
WindowWidth=200
WindowHeight=200
UpperLeftX=INT((DisplayWidth-WindowWidth)/2)
UpperLeftY=INT((DisplayHeight-WindowHeight)/2)
OPEN "My Stoplight" FOR GRAPHICS_nsb AS #cw 'Show the Choice Window
PRINT #cw, "trapclose [quit]"
PRINT #cw, "down"
[setUp] 'Default window
PRINT #cw, "fill buttonface" 'Fill graphic box with user's default system background color
PRINT #cw, "backcolor 0 132 0" 'Sets fill color dull green
PRINT #cw, "color BLACK" 'Sets pen color
PRINT #cw, "size 2"
PRINT #cw, "place 20 20" 'Position the pen
PRINT #cw, "circlefilled 10" 'Draw a filled circle
PRINT #cw, "place 10 140" 'Places the pen
PRINT #cw, "backcolor 232 232 157" 'Sets fill color dull yellow
PRINT #cw, "color BLACK" 'Sets pen color
PRINT #cw, "place 20 60" 'Position the pen
PRINT #cw, "circlefilled 10" 'Draw a filled circle
PRINT #cw, "backcolor 223 0 0" 'Sets fill color dull red
PRINT #cw, "color BLACK" 'Sets pen color
PRINT #cw, "place 20 100" 'Position the pen
PRINT #cw, "circlefilled 10" 'Draw a filled circle
PRINT #cw, "place 10 140" 'Places the pen
PRINT #cw, "color BLACK" 'Change the color of the pen
PRINT #cw, "backcolor buttonface" 'Background color of the text
PRINT #cw, "\Click A Color!" 'Message to user
PRINT #cw, "flush" 'Commits current set of commands to memory for to make graphics stick
PRINT #cw, "discard" 'Rids all commands prior to last flush to free memory
PRINT #cw, "when leftButtonDown [setNewColors]" 'Branch if aim is good
WAIT
[setNewColors] 'Get mouse position to make choice
IF (MouseX >12 AND MouseX < 28) AND (MouseY >12 and MouseY <28) THEN sel=1
IF (MouseX >12 AND MouseX < 28) AND (MouseY >52 and MouseY <68) THEN sel=2
IF (MouseX >12 AND MouseX < 28) AND (MouseY >92 and MouseY <108) THEN sel=3
SELECT CASE sel 'Set new colors and message
CASE 1 'Green button is pressed
col$="GREEN"
msg$="GREEN!"
loc$="20 20"
CASE 2 'Yellow button is pressed
col$="YELLOW"
msg$="YELLOW!"
loc$="20 60"
CASE 3
col$="RED" 'Red button is pressed
msg$="RED!"
loc$="20 100"
CASE ELSE
GOTO [setUp]
END SELECT
[tempSetup] 'Draw Temp Window
PRINT #cw, "place 10 140" 'Places the pen
PRINT #cw, "down"
PRINT #cw, "backcolor "; col$ 'Set a new color based on button pressed
PRINT #cw, "place "; loc$ 'Position the pen
PRINT #cw, "circlefilled 10" 'Draw a filled circle
PRINT #cw, "place 10 140" 'Places the pen
PRINT #cw, "backcolor buttonface" 'Background color of the text
PRINT #cw, "\You pressed "; msg$ 'Message to user
CALL shortPause 'Do shortPause then come back here
sel=0 : MouseX=0 : MouseY=0 'Re-set values to zero before new [setUp]
GOTO [setUp] 'Go back to the Default Window
WAIT
[quit]
CLOSE #cw
END
SUB shortPause
print #cw, "disable" 'Prevents mouse input during shortPause
TIMER 2500, [cont] 'Set pause here, more is longer.
WAIT
[cont]
TIMER 0
print #cw, "enable" 'Enable the window again
END SUB
At the end of the [tempSetup], Pablo reset sel, MouseX and MouseY to zero to force the program to get new input from the user and not redraw the graphics window with the same colors and message.
I originally started with a simple graphics window to click on a graphic, retrieve the MouseX and MouseY location of the click, and then branch to another routine in my code. I haven't yet written those branch routines, but they could go in place of CALL shortPause which I'm using only for demonstration purposes here, or in the SELECT CASE block of code. After completing the actions in the branch routines, each routine would end with a GOTO [setUp] where the user can make another choice, or shoot again, or something else.
This demo has only three buttons to be clicked, but the same code can be adapted for many buttons to perform many actions, including an EXIT if desired. By starting with a simple Window for Graphics and adding small blocks of code, I've got a pretty nifty little piece of eye-candy which could be used for several types of graphic games. I'm glad I listened to Pablo for hints on how my code could be tightened up, and for that swell trick to get RGB values for the colors I want, and get them right the first time.
By the way, Pablo assured me this code can be run in Just Basic as well as in Liberty Basic. Just Basic doesn't support the colordialog command, though. For finding RGB color values in Just Basic, you can use MSPaint © Microsoft, or, better yet, download [ J-ColorPick] written by John Davidson.
The file ( stoplight.bas ) is included in the zipped archive of this newsletter.
::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::